/********************************************************************************


 **** Copyright (C), 2024, Yuanlong Xu <Yono233@outlook.com>    ****
 **** All rights reserved                                       ****

 ********************************************************************************
 * File Name     : MBx_utility_err_trace.c
 * Author        : yono
 * Date          : 2024-07-23
 * Version       : 1.0
********************************************************************************/
/**************************************************************************/
/*
    modbusX CRC-modbus16计算模块
            使用查表法，较消耗ROM
            若资源极其受限的芯片则应当自己使用硬件CRC或其他方法生成
*/

/* Includes ------------------------------------------------------------------*/
#include <MBx_api.h>
#if !MBX_BUILT_UTILTY_CRC_ENABLE
/* Private types -------------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private Constants ---------------------------------------------------------*/
static const uint16_t crc16tab[256] = {
    0x0000U, 0xC1C0U, 0x81C1U, 0x4001U, 0x01C3U, 0xC003U, 0x8002U, 0x41C2U, 0x01C6U, 0xC006U, 0x8007U, 0x41C7U, 0x0005U, 0xC1C5U, 0x81C4U, 0x4004U, 0x01CCU, 0xC00CU, 0x800DU, 0x41CDU, 0x000FU, 0xC1CFU, 0x81CEU, 0x400EU, 0x000AU, 0xC1CAU, 0x81CBU, 0x400BU, 0x01C9U, 0xC009U, 0x8008U, 0x41C8U,
    0x01D8U, 0xC018U, 0x8019U, 0x41D9U, 0x001BU, 0xC1DBU, 0x81DAU, 0x401AU, 0x001EU, 0xC1DEU, 0x81DFU, 0x401FU, 0x01DDU, 0xC01DU, 0x801CU, 0x41DCU, 0x0014U, 0xC1D4U, 0x81D5U, 0x4015U, 0x01D7U, 0xC017U, 0x8016U, 0x41D6U, 0x01D2U, 0xC012U, 0x8013U, 0x41D3U, 0x0011U, 0xC1D1U, 0x81D0U, 0x4010U,
    0x01F0U, 0xC030U, 0x8031U, 0x41F1U, 0x0033U, 0xC1F3U, 0x81F2U, 0x4032U, 0x0036U, 0xC1F6U, 0x81F7U, 0x4037U, 0x01F5U, 0xC035U, 0x8034U, 0x41F4U, 0x003CU, 0xC1FCU, 0x81FDU, 0x403DU, 0x01FFU, 0xC03FU, 0x803EU, 0x41FEU, 0x01FAU, 0xC03AU, 0x803BU, 0x41FBU, 0x0039U, 0xC1F9U, 0x81F8U, 0x4038U,
    0x0028U, 0xC1E8U, 0x81E9U, 0x4029U, 0x01EBU, 0xC02BU, 0x802AU, 0x41EAU, 0x01EEU, 0xC02EU, 0x802FU, 0x41EFU, 0x002DU, 0xC1EDU, 0x81ECU, 0x402CU, 0x01E4U, 0xC024U, 0x8025U, 0x41E5U, 0x0027U, 0xC1E7U, 0x81E6U, 0x4026U, 0x0022U, 0xC1E2U, 0x81E3U, 0x4023U, 0x01E1U, 0xC021U, 0x8020U, 0x41E0U,
    0x01A0U, 0xC060U, 0x8061U, 0x41A1U, 0x0063U, 0xC1A3U, 0x81A2U, 0x4062U, 0x0066U, 0xC1A6U, 0x81A7U, 0x4067U, 0x01A5U, 0xC065U, 0x8064U, 0x41A4U, 0x006CU, 0xC1ACU, 0x81ADU, 0x406DU, 0x01AFU, 0xC06FU, 0x806EU, 0x41AEU, 0x01AAU, 0xC06AU, 0x806BU, 0x41ABU, 0x0069U, 0xC1A9U, 0x81A8U, 0x4068U,
    0x0078U, 0xC1B8U, 0x81B9U, 0x4079U, 0x01BBU, 0xC07BU, 0x807AU, 0x41BAU, 0x01BEU, 0xC07EU, 0x807FU, 0x41BFU, 0x007DU, 0xC1BDU, 0x81BCU, 0x407CU, 0x01B4U, 0xC074U, 0x8075U, 0x41B5U, 0x0077U, 0xC1B7U, 0x81B6U, 0x4076U, 0x0072U, 0xC1B2U, 0x81B3U, 0x4073U, 0x01B1U, 0xC071U, 0x8070U, 0x41B0U,
    0x0050U, 0xC190U, 0x8191U, 0x4051U, 0x0193U, 0xC053U, 0x8052U, 0x4192U, 0x0196U, 0xC056U, 0x8057U, 0x4197U, 0x0055U, 0xC195U, 0x8194U, 0x4054U, 0x019CU, 0xC05CU, 0x805DU, 0x419DU, 0x005FU, 0xC19FU, 0x819EU, 0x405EU, 0x005AU, 0xC19AU, 0x819BU, 0x405BU, 0x0199U, 0xC059U, 0x8058U, 0x4198U,
    0x0188U, 0xC048U, 0x8049U, 0x4189U, 0x004BU, 0xC18BU, 0x818AU, 0x404AU, 0x004EU, 0xC18EU, 0x818FU, 0x404FU, 0x018DU, 0xC04DU, 0x804CU, 0x418CU, 0x0044U, 0xC184U, 0x8185U, 0x4045U, 0x0187U, 0xC047U, 0x8046U, 0x4186U, 0x0182U, 0xC042U, 0x8043U, 0x4183U, 0x0041U, 0xC181U, 0x8180U, 0x4040U,
};
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/**
 * @brief  CRC-modbus16计算 默认查表法
 * @param data 期望计算的数据内存头指针
 * @param len 期望计算的数据字节长度
 * @return 计算得到的CRC-modbus16值
 */
uint16_t MBx_utility_crc16(uint8_t *data, uint16_t len)
{
    int      counter;
    uint16_t crc = 0xFFFF;
    for(counter = 0; counter < len; counter++)
    {
        crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ *data++) & 0x00FF];
    }
    return ((crc << 8) | (crc >> 8));
}

#else

/**
 * @brief  CRC-modbus16计算 不开启内部CRC算法表示无法接受表查找额外的RAM消耗
 *              采用一个可被覆盖定义的普通计算方式，防止未定义
 * @param data 期望计算的数据内存头指针
 * @param len 期望计算的数据字节长度
 * @return 计算得到的CRC-modbus16值
 */
__weak uint16_t MBx_utility_crc16(uint8_t *data, uint16_t len)
{
    uint16_t crc = 0xFFFF; // CRC寄存器初始值
    uint16_t i;
    uint8_t  j;
    for(i = 0; i < len; i++)
    {
        crc ^= data[i]; // 将数据字节与CRC进行异或
        for(j = 0; j < 8; j++)
        {
            if(crc & 0x0001)
            {
                crc = (crc >> 1) ^ 0xA001;
            }
            else
            {
                crc >>= 1;
            }
        }
    }
    return crc; // 返回计算得到的CRC值
}

#endif /* MBX_BUILT_UTILTY_CRC_ENABLE */
